#include "board.h"
#include <rtdevice.h>
#include <rtdef.h>

static int adc_init(struct rt_adc_device *adc)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

	ADC_CommonStructInit(&ADC_CommonInitStructure);
	ADC_CommonInitStructure.ADC_Mode             = ADC_Mode_Independent;
	ADC_CommonInitStructure.ADC_Prescaler        = ADC_Prescaler_Div8;
	ADC_CommonInitStructure.ADC_DMAAccessMode    = ADC_DMAAccessMode_Disabled;
	ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
	ADC_CommonInit(&ADC_CommonInitStructure);

	ADC_StructInit(&ADC_InitStructure);
	ADC_InitStructure.ADC_ContinuousConvMode       = DISABLE;
	ADC_InitStructure.ADC_Resolution               = ADC_Resolution_12b;
	ADC_InitStructure.ADC_ExternalTrigConv         = ADC_ExternalTrigConv_T1_CC1;
	ADC_InitStructure.ADC_ExternalTrigConvEdge     = ADC_ExternalTrigConvEdge_None;
	ADC_InitStructure.ADC_DataAlign                = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfConversion          = 1;
	ADC_InitStructure.ADC_ScanConvMode             = DISABLE;
	ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_56Cycles);
    ADC_Cmd(ADC1, ENABLE);

    return 0;
}

static void adc_deinit(struct rt_adc_device *adc)
{

}

static int adc_convert(struct rt_adc_device *device, uint32_t channel, int32_t *value)
{
    ADC_SoftwareStartConv(ADC1);
    *value = ADC_GetConversionValue(ADC1);

    return 0;
}

static const struct rt_adc_ops _adcops = {
    .init = adc_init,
    .deinit = adc_deinit,
    .convert = adc_convert,
};

static struct rt_adc_device _adc0;

int adc_drv_init(void)
{
    _adc0.ops = &_adcops;

    _adc0.info.channels = 1;
    _adc0.info.sampling_max = 4095;
    _adc0.info.sampling_min = 0;
    _adc0.info.vref = 3.3;

    return rt_hw_adc_register(&_adc0, "adc0", 0);
}
INIT_DEVICE_EXPORT(adc_drv_init);
